﻿using System;
using System.IO;
using AdAggregator.Advertisement;
using FluentScheduler;

namespace AdAggregator.Monitoring
{
    public class PriceMonitoringRegistry<TPricedAdvertisement> : Registry where TPricedAdvertisement : IPricedAdvertisement
    {
        private const string PriceFileExt = ".price";

        public static void RegisterTask(IMonitoringTask task, TPricedAdvertisement lastAd, Action<MonitoringResult<TPricedAdvertisement>> callback)
        {
            if (lastAd.Price.HasValue) SetPreviousPrice(task.Id, lastAd.Price.Value);
            TaskManager.AddTask(TaskAction(task, lastAd, callback), s => s.WithName(task.Id).ToRunNow().AndEvery(task.Frequency).Minutes());
        }

        public static void UnregisterTask(IMonitoringTask task)
        {
            TaskManager.RemoveTask(task.Id);
        }

        private static Action TaskAction(IMonitoringTask task, TPricedAdvertisement ad, Action<MonitoringResult<TPricedAdvertisement>> callback)
        {
            return () =>
                {
                    var newestVersionOfAd = (TPricedAdvertisement)ad.Source.GetNewestVersionOfAd(ad.Link);
                    var previousPrice = GetPreviousPrice(task.Id);
                    if (newestVersionOfAd.Price.HasValue && previousPrice.HasValue && newestVersionOfAd.Price.Value != previousPrice)
                    {
                        SetPreviousPrice(task.Id, newestVersionOfAd.Price.Value);
                        var monitoringResult = new MonitoringResult<TPricedAdvertisement>
                            {
                                PricedAdvertisement = newestVersionOfAd,
                                MonitoringTaskId = task.Id,
                                LastUpdate = DateTime.Now
                            };
                        callback(monitoringResult);
                    }
                };
        }

        private static void SetPreviousPrice(string id, decimal value)
        {
            var filename = id + PriceFileExt;
            using (var stream = new StreamWriter(filename, false))
            {
                stream.WriteLine(value);
            }
        }

        private static decimal? GetPreviousPrice(string id)
        {
            var filename = id + PriceFileExt;
            if (!File.Exists(filename)) return null;
            string value;
            using (var stream = new StreamReader(filename))
            {
                value = stream.ReadLine();
            }
            decimal price;
            if (decimal.TryParse(value, out price))
            {
                return price;
            }
            return null;
        }
    }
}
